from IPython.display import display
from bokeh.plotting import output_notebook
from bokeh.plotting import show
import geopandas as gpd
from shapely.geometry import Point
from shapely.ops import linemerge
from easy_map_bokeh import EasyMapBokeh
from osmgt import OsmGt
from graph_tool.topology import shortest_path
output_notebook()
location = "Roanne"
%%time
pois_gdf = OsmGt.pois_from_location(location).get_gdf()
display(pois_gdf.head(2))
%%time
roads_initialized = OsmGt.roads_from_location(
location,
mode="vehicle",
additional_nodes=pois_gdf
)
roads_gdf = roads_initialized.get_gdf()
display(roads_gdf.head(2))
%%time
layers_to_add = [
{
"input_gdf": roads_gdf,
"legend": "roads",
"color": "black",
},
{
"input_gdf": pois_gdf,
"legend": "POIs",
"style": "square",
"color": "blue",
"size": 9
},
]
my_map = EasyMapBokeh(
"My roads and POIs",
layers=layers_to_add
)
show(my_map.figure)
%%time
roads_topology_gdfs = roads_initialized.topology_checker()
lines_unchanged = roads_topology_gdfs["lines_unchanged"]
lines_added = roads_topology_gdfs["lines_added"]
lines_split = roads_topology_gdfs["lines_split"]
nodes_added = roads_topology_gdfs["nodes_added"]
intersections_added = roads_topology_gdfs["intersections_added"]
layers_to_add = [
{
"input_gdf": lines_unchanged,
"legend": "roads unchanged",
"color": "black",
},
{
"input_gdf": lines_added,
"legend": "roads added",
"color": "green",
},
{
"input_gdf": lines_split,
"legend": "roads split",
"color": "orange",
},
{
"input_gdf": intersections_added,
"legend": "Intersections added",
"color": "brown",
},
{
"input_gdf": nodes_added,
"legend": "Nodes added", # POIs here
"style": "square",
"color": "blue",
"size": 9
},
]
my_map = EasyMapBokeh(
"Topology about my roads and POIs",
layers=layers_to_add
)
show(my_map.figure)
%%time
graph = roads_initialized.get_graph()
# a plot method has been added on OsmGT.
graph.plot()
%%time
# now, we have to define a start point and a end point and get their wkt
start_node_topo_uuid = 47
end_node_topo_uuid = 63
# 'topo_uuid' is generated by osmgt (during the topology processing).
# Some roads has been split that's whyso this id has been created.
start_node_gdf = pois_gdf[pois_gdf['topo_uuid'] == start_node_topo_uuid]
end_node_gdf = pois_gdf[pois_gdf['topo_uuid'] == end_node_topo_uuid]
start_node_wkt = start_node_gdf.iloc[0]["geometry"].wkt
end_node_wkt = end_node_gdf.iloc[0]["geometry"].wkt
# the graph have some methods (graph-tools method always exists!) to find egdes, vertices... Let's use the .find_vertex_from_name(). the wkt is the vertex name...
source_vertex = graph.find_vertex_from_name(start_node_wkt)
target_vertex = graph.find_vertex_from_name(end_node_wkt)
# shortest path computing...
path_vertices, path_edges = shortest_path(
graph,
source=source_vertex,
target=target_vertex,
weights=graph.edge_weights # weigth is based on line length
)
# get path by using edge names
roads_ids = [
graph.edge_names[edge]
for edge in path_edges
]
roads_gdf_copy = roads_gdf.copy(deep=True)
shortest_path_found = roads_gdf_copy[roads_gdf['topo_uuid'].isin(roads_ids)].to_crs(3857)['geometry'].to_list()
shortest_path_found_gdf = gpd.GeoDataFrame(index=[0], crs="EPSG:3857", geometry=[linemerge(shortest_path_found)])
layers_to_add = [
{
"input_gdf": shortest_path_found_gdf,
"legend": "shortest_path",
"color": "red",
"line_width": 5
},
{
"input_gdf": start_node_gdf,
"legend": "source node",
"color": "blue",
"style": "circle",
"size": 9
},
{
"input_gdf": end_node_gdf,
"legend": "target node",
"color": "green",
"style": "circle",
"size": 9
},
]
my_shortest_path_map = EasyMapBokeh(
"My shortest path 1",
layers=layers_to_add
)
show(my_shortest_path_map.figure)
%%time
start_node_topo_uuid = 47
end_node_topo_uuid = 63
start_node_gdf = pois_gdf[pois_gdf['topo_uuid'] == start_node_topo_uuid]
end_node_gdf = pois_gdf[pois_gdf['topo_uuid'] == end_node_topo_uuid]
start_node = start_node_gdf.iloc[0]["geometry"]
end_node = end_node_gdf.iloc[0]["geometry"]
shortest_paths = OsmGt.shortest_path_from_location(
"Roanne",
[
(start_node, end_node),
(start_node, end_node), # duplicate pairs are cleaned
],
mode="pedestrian"
)
layers_to_add = [
{
"input_gdf": shortest_paths[["geometry"]],
"legend": "shortest_path",
"color": "red",
"line_width": 5
},
{
"input_gdf": start_node_gdf,
"legend": "source node",
"color": "blue",
"style": "circle",
"size": 9
},
{
"input_gdf": end_node_gdf,
"legend": "target node",
"color": "green",
"style": "circle",
"size": 9
},
]
my_shortest_path_map = EasyMapBokeh(
"My shortest path 2",
layers=layers_to_add
)
show(my_shortest_path_map.figure)
display(shortest_paths)
%%time
start_node_topo_uuid = 47
source_node = pois_gdf[pois_gdf['topo_uuid'] == start_node_topo_uuid]
# 2 = 2 min ; 5 = 5 min ; 10 = 10 min
isochrones_polygon_values = {
2: "#d9ef8b",
5: "#fee08b",
10: "#f46d43"
}
isochrones_lines_values = {
2: "#668100",
5: "#e2a803",
10: "#962603"
}
trip_speed = 3 # km/h
location_point = source_node.iloc[0]["geometry"]
isochrones_polygons, isochrones_lines = OsmGt.isochrone_from_source_node(
location_point,
list(isochrones_polygon_values.keys()),
trip_speed,
mode="pedestrian"
)
isochrones_polygons["color"] = isochrones_polygons["iso_name"].map(lambda x: isochrones_polygon_values[int(x.split(" ")[0])])
isochrones_lines["color"] = isochrones_lines["iso_name"].map(lambda x: isochrones_lines_values[int(x.split(" ")[0])])
layers_to_add = [
{
"input_gdf": isochrones_polygons,
"legend": "iso_name",
"fill_color": "color",
"line_color": "color",
"fill_alpha": 0.5
},
{
"input_gdf": source_node,
"legend": "Source node",
"style": "circle",
"color": "red",
"size": 5
},
{
"input_gdf": isochrones_lines,
"legend": "iso_name",
"color": "color",
"line_width": 2
},
]
my_shortest_path_map = EasyMapBokeh(
"Isochrones from times",
layers=layers_to_add
)
show(my_shortest_path_map.figure)
print("\nIsochrones polygons output")
display(isochrones_polygons)
print("\nIsochrones lines output")
display(isochrones_lines.head(2))
%%time
start_node_topo_uuid = 47
source_node = pois_gdf[pois_gdf['topo_uuid'] == start_node_topo_uuid]
trip_speed = 3 # km/h
isochrones_polygon_values = {
500: "#d9ef8b",
750: "#fee08b",
1000: "#f46d43"
}
# 2 = 2 min ; 5 = 5 min ; 10 = 10 min
isochrones_lines_values = {
500: "#668100",
750: "#e2a803",
1000: "#962603"
}
location_point = source_node.iloc[0]["geometry"]
isochrones_polygons, isochrones_lines = OsmGt.isochrone_distance_from_source_node(
location_point,
list(isochrones_polygon_values.keys()), # meters
trip_speed,
mode="pedestrian"
)
isochrones_polygons["color"] = isochrones_polygons["iso_distance"].map(lambda x: isochrones_polygon_values[x])
isochrones_lines["color"] = isochrones_lines["iso_distance"].map(lambda x: isochrones_lines_values[x])
layers_to_add = [
{
"input_gdf": isochrones_polygons,
"legend": "iso_distance",
"fill_color": "color",
"line_color": "color",
"fill_alpha": 0.5
},
{
"input_gdf": isochrones_lines,
"legend": "iso_distance",
"color": "color",
"line_width": 2
},
{
"input_gdf": source_node,
"legend": "Source node",
"style": "circle",
"color": "orange",
"size": 15
},
]
my_shortest_path_map = EasyMapBokeh(
"Isochrones from distance",
layers=layers_to_add
)
show(my_shortest_path_map.figure)
%%time
# we can change the isochrone style
start_node_topo_uuid = 47
source_node = pois_gdf[pois_gdf['topo_uuid'] == start_node_topo_uuid]
# 2 = 2 min ; 5 = 5 min ; 10 = 10 min
isochrones_polygon_values = {
2: "#d9d9d9",
5: "#969696",
10: "#525252"
}
isochrones_lines_values = {
2: "#bdbdbd",
5: "#737373",
10: "#252525"
}
trip_speed = 3 # km/h
location_point = source_node.iloc[0]["geometry"]
isochrones_polygons, isochrones_lines = OsmGt.isochrone_from_source_node(
location_point,
list(isochrones_polygon_values.keys()),
trip_speed,
mode="pedestrian",
display_mode="web" # HERE you can change the style (orthogonal by default, or web)
)
isochrones_polygons["color"] = isochrones_polygons["iso_name"].map(lambda x: isochrones_polygon_values[int(x.split(" ")[0])])
isochrones_lines["color"] = isochrones_lines["iso_name"].map(lambda x: isochrones_lines_values[int(x.split(" ")[0])])
layers_to_add = [
{
"input_gdf": isochrones_polygons,
"legend": "iso_name",
"fill_color": "color",
"line_color": "color",
"fill_alpha": 0.5
},
{
"input_gdf": source_node,
"legend": "Source node",
"style": "circle",
"color": "red",
"size": 5
},
{
"input_gdf": isochrones_lines,
"legend": "iso_name",
"color": "color",
"line_width": 2
},
]
my_shortest_path_map = EasyMapBokeh(
"Isochrones from times",
layers=layers_to_add
)
show(my_shortest_path_map.figure)
print("\nIsochrones polygons output")
display(isochrones_polygons)
print("\nIsochrones lines output")
display(isochrones_lines.head(2))